home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / remin301.zip / REMIN300.ZIP / MAIN.C < prev    next >
C/C++ Source or Header  |  1992-11-10  |  32KB  |  1,103 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  MAIN.C                                                     */
  4. /*                                                             */
  5. /*  Main program loop, as well as miscellaneous conversion     */
  6. /*  routines, etc.                                             */
  7. /*                                                             */
  8. /*  This file is part of REMIND.                               */
  9. /*  Copyright (C) 1992 by David F. Skoll.                      */
  10. /*                                                             */
  11. /***************************************************************/
  12. #include "config.h"
  13. #ifdef HAVE_STDLIB_H
  14. #include <stdlib.h>
  15. #endif
  16. #ifdef HAVE_MALLOC_H
  17. #include <malloc.h>
  18. #endif
  19. #include <stdio.h>
  20. #include <string.h>
  21. #ifdef HAVE_STDARG
  22. #include <stdarg.h>
  23. #else
  24. #include <varargs.h>
  25. #endif
  26. #include <ctype.h>
  27.  
  28. #ifdef __MSDOS__
  29. #include <dos.h>
  30. #endif
  31.  
  32.  
  33. #ifndef __MSDOS__
  34. #include <sys/types.h>
  35. #ifdef SYSV
  36. #include <time.h>
  37. #else
  38. #include <sys/time.h>
  39. #endif
  40. #endif /* ifndef __MSDOS__ */
  41.  
  42. #include "types.h"
  43. #include "protos.h"
  44. #include "expr.h"
  45. #include "globals.h"
  46. #include "err.h"
  47.  
  48. PRIVATE void DoReminders ARGS ((void));
  49.  
  50. static char TPushBuffer[TOKSIZE+1]; /* Buffer for pushing back a token. */
  51. static char *TokenPushed = NULL;
  52.  
  53.  
  54. /***************************************************************/
  55. /***************************************************************/
  56. /**                                                           **/
  57. /**  Main Program Loop                                        **/
  58. /**                                                           **/
  59. /***************************************************************/
  60. /***************************************************************/
  61. #ifdef HAVE_PROTOS
  62. PUBLIC int main(int argc, char *argv[])
  63. #else
  64. int main(argc, argv)
  65. int argc;
  66. char *argv[];
  67. #endif
  68. {
  69. #ifdef HAVE_QUEUED
  70.    int pid;
  71. #endif
  72.  
  73. /* The very first thing to do is to set up ErrFp to be stderr */
  74.    ErrFp = stderr;
  75.    
  76. /* Set up global vars */
  77.    ArgC = argc;
  78.    ArgV = argv;
  79.  
  80.    InitRemind(argc, argv);
  81.    if(DoCalendar || DoSimpleCalendar) {
  82.       ProduceCalendar();
  83.       return 0;
  84.    }
  85.  
  86.    /* Not doing a calendar.  Do the regular remind loop */
  87.    DoReminders();
  88.  
  89.    if (DebugFlag & DB_DUMP_VARS) DumpVarTable();
  90.  
  91.    if (!Hush) {
  92.       if (DestroyOmitContexts())
  93.     Eprint("Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT.");
  94. #ifdef HAVE_QUEUED
  95.       if (!Daemon && !NextMode && !NumTriggered && !NumQueued) printf("No reminders.\n");
  96.    else
  97.       if (!Daemon && !NextMode && !NumTriggered) printf("%d reminder%s queued for later today.\n",
  98.          NumQueued, (NumQueued == 1) ? "" : "s");
  99. #else
  100.       if (!NextMode && !NumTriggered) printf("No reminders.\n");
  101. #endif
  102.    }
  103.  
  104.    /* If it's MS-DOS, reset the file access date */
  105. #ifdef __MSDOS__
  106.    if (RealToday == JulianToday) SetAccessDate(InitialFile, RealToday);
  107. #endif
  108.  
  109.    /* If there are any background reminders queued up, handle them */
  110. #ifdef HAVE_QUEUED
  111.    if (NumQueued || Daemon) {
  112.  
  113.       if (DontFork) {
  114.      HandleQueuedReminders();
  115.      return 0;
  116.       } else {
  117.      pid = fork();
  118.      if (pid == 0) {
  119.         HandleQueuedReminders();
  120.         return 0;
  121.      }
  122.      if (pid == -1) {
  123.         fprintf(ErrFp, "Couldn't fork to do queued reminders.\n");
  124.         return 1;
  125.      }
  126.       }
  127.    }
  128. #endif
  129.  
  130.    return 0;
  131. }
  132.  
  133. /***************************************************************/
  134. /*                                                             */
  135. /*  DoReminders                                                */
  136. /*                                                             */
  137. /*  The normal case - we're not doing a calendar.              */
  138. /*                                                             */
  139. /***************************************************************/
  140. #ifdef HAVE_PROTOS
  141. PRIVATE void DoReminders(void)
  142. #else
  143. static void DoReminders()
  144. #endif
  145. {
  146.    int r;
  147.    Token tok;
  148.    char *s;
  149.    Parser p;
  150.  
  151.    FileAccessDate = GetAccessDate(InitialFile);
  152.  
  153.    if (FileAccessDate < 0) {
  154.       fprintf(ErrFp, "remind: Can't access file '%s'.\n", InitialFile);
  155.       exit(1);
  156.    }
  157.  
  158.    r=OpenFile(InitialFile);
  159.    if (r) {
  160.       fprintf(ErrFp, "Can't read %s: %s\n", InitialFile, ErrMsg[r]);
  161.       exit(1);
  162.    }
  163.  
  164.    while(1) {
  165.       r = ReadLine();
  166.       if (r == E_EOF) return;
  167.       if (r) {
  168.      Eprint("Error reading file: %s", ErrMsg[r]);
  169.      exit(1);
  170.       }
  171.       s = FindInitialToken(&tok, CurLine);
  172.  
  173.       /* Should we ignore it? */
  174.       if (NumIfs &&
  175.           tok.type != T_If &&
  176.           tok.type != T_Else &&
  177.           tok.type != T_EndIf &&
  178.           tok.type != T_IfTrig &&
  179.           ShouldIgnoreLine())
  180.       {
  181.           /*** IGNORE THE LINE ***/
  182.       }
  183.       else {
  184.          /* Create a parser to parse the line */
  185.          CreateParser(s, &p);
  186.          switch(tok.type) {
  187.  
  188.             case T_Empty:
  189.         case T_Comment:
  190.            break;
  191.  
  192.         case T_Rem:     r=DoRem(&p);     break;
  193.         case T_ErrMsg:  r=DoErrMsg(&p);  break;
  194.         case T_If:      r=DoIf(&p);      break;
  195.         case T_IfTrig:  r=DoIfTrig(&p);  break;
  196.         case T_Else:    r=DoElse(&p);    break;
  197.         case T_EndIf:   r=DoEndif(&p);   break;
  198.         case T_Include: r=DoInclude(&p); break;
  199.         case T_Exit:    exit(99);        break;
  200.         case T_Set:     r=DoSet(&p);     break;
  201.         case T_Fset:    r=DoFset(&p);    break;
  202.         case T_UnSet:   r=DoUnset(&p);   break;
  203.         case T_Clr:     r=DoClear(&p);   break;
  204.             case T_Debug:   r=DoDebug(&p);   break;
  205.         case T_Dumpvars: r=DoDump(&p);   break;
  206.         case T_Banner:  r=DoBanner(&p);  break;
  207.         case T_Omit:    r=DoOmit(&p);
  208.                        if (r == E_PARSE_AS_REM) {
  209.                    DestroyParser(&p);
  210.                    CreateParser(s, &p);
  211.                    r=DoRem(&p);
  212.                 }
  213.                     break;
  214.         case T_Pop:     r=PopOmitContext(&p);     break;
  215.         case T_Preserve: r=DoPreserve(&p);  break;
  216.         case T_Push:    r=PushOmitContext(&p);    break;
  217.         case T_RemType: if (tok.val == RUN_TYPE) {
  218.                                r=DoRun(&p);
  219.                                break;
  220.                  } else {
  221.                     CreateParser(CurLine, &p);
  222.                 r=DoRem(&p);
  223.                 break;
  224.                  }
  225.                  
  226.  
  227.      /* If we don't recognize the command, do a REM by default */
  228.      /* Note:  Since the parser hasn't been used yet, we don't */
  229.      /* need to destroy it here. */
  230.  
  231.         default:        CreateParser(CurLine, &p); r=DoRem(&p); break;
  232.          }
  233.          if (r && (!Hush || r != E_RUN_DISABLED)) Eprint("%s", ErrMsg[r]);
  234.  
  235.          /* Destroy the parser - free up resources it may be tying up */
  236.          DestroyParser(&p);
  237.       }
  238.    }
  239. }
  240.  
  241. /***************************************************************/
  242. /*                                                             */
  243. /*  Julian                                                     */
  244. /*                                                             */
  245. /*  Given day, month, year, return Julian date in days since   */
  246. /*  1 January 1990.                                            */
  247. /*                                                             */
  248. /***************************************************************/
  249. #ifdef HAVE_PROTOS
  250. PUBLIC int Julian(int year, int month, int day)
  251. #else
  252. int Julian(year, month, day)
  253. int day, month, year;
  254. #endif
  255. {
  256.    register int jul, iy;
  257.  
  258.    if (year < BASE) return -1;
  259.  
  260.    if (JulFirst == -1 || year < FirstYear) {
  261.       jul = 0;
  262.       for (iy = BASE; iy < year; iy++) jul += DaysInYear(iy);
  263.    } else {
  264.       jul = JulFirst;
  265.       for (iy = FirstYear; iy < year; iy++) jul += DaysInYear(iy);
  266.    }
  267.  
  268.    return jul + MonthIndex[IsLeapYear(year)][month] + day - 1;
  269. }
  270.  
  271. /***************************************************************/
  272. /*                                                             */
  273. /*  FromJulian                                                 */
  274. /*                                                             */
  275. /*  Convert a Julian date to year, month, day.                 */
  276. /*                                                             */
  277. /***************************************************************/
  278. #ifdef HAVE_PROTOS
  279. PUBLIC void FromJulian(int jul, int *y, int *m, int *d)
  280. #else
  281. void FromJulian(jul, y, m, d)
  282. int jul;
  283. int *y, *m, *d;
  284. #endif
  285. {
  286.    register int t;
  287.  
  288.    if (jul >= JulFirst && JulFirst != -1) {
  289.       *y = FirstYear;
  290.       jul -= JulFirst;
  291.    } else *y = BASE;
  292.  
  293.    *m = 0;
  294.  
  295.    t = DaysInYear(*y);
  296.    while (jul >= t) {
  297.       jul -= t;
  298.       (*y)++;
  299.       t = DaysInYear(*y);
  300.    }
  301.  
  302.    t = DaysInMonth(*m, *y);
  303.    while (jul >= t) {
  304.       jul -= t;
  305.       (*m)++;
  306.       t = DaysInMonth(*m, *y);
  307.    }
  308.    *d = jul + 1;
  309.    return;
  310. }
  311.  
  312. /***************************************************************/
  313. /*                                                             */
  314. /*  ParseChar                                                  */
  315. /*                                                             */
  316. /*  Parse a character from a parse pointer.  If peek is non-   */
  317. /*  zero, then just peek ahead; don't advance pointer.         */
  318. /*                                                             */
  319. /***************************************************************/
  320. #ifdef HAVE_PROTOS
  321. PUBLIC int ParseChar(ParsePtr p, int *err, int peek)
  322. #else
  323. int ParseChar(p, err, peek)
  324. ParsePtr p;
  325. int *err;
  326. int peek;
  327. #endif
  328. {
  329.    Value val;
  330.    int r;
  331.  
  332.    *err = 0;
  333.    if (TokenPushed && *TokenPushed)
  334.       if (peek) return *TokenPushed;
  335.       else      return *TokenPushed++;
  336.  
  337.    while(1) {
  338.       if (p->isnested) {
  339.      if (*(p->epos))
  340.         if (peek) return *(p->epos);
  341.         else      return *(p->epos++);
  342.      free(p->etext);  /* End of substituted expression */
  343.      p->etext = NULL;
  344.      p->epos = NULL;
  345.      p->isnested = 0;
  346.       }
  347.       if (!*(p->pos)) {
  348.      return 0;
  349.       }
  350.       if (*p->pos != BEG_OF_EXPR || !p->allownested)
  351.      if (peek) return *(p->pos);
  352.      else      return *(p->pos++);
  353.       p->pos++;
  354.       r = EvalExpr(&(p->pos), &val);
  355.       if (r) {
  356.      *err = r;
  357.      DestroyParser(p);
  358.      return 0;
  359.       }
  360.       if (*p->pos != END_OF_EXPR) {
  361.      *err = E_MISS_END;
  362.      DestroyParser(p);
  363.      DestroyValue(&val);
  364.      return 0;
  365.       }
  366.       p->pos++;
  367.       r = DoCoerce(STR_TYPE, &val);
  368.       if (r) { *err = r; return 0; }
  369.       p->etext = val.v.str;
  370.       val.type = ERR_TYPE; /* So it's not accidentally destroyed! */
  371.       p->isnested = 1;
  372.       p->epos = p->etext;
  373.    }
  374. }
  375.  
  376. /***************************************************************/
  377. /*                                                             */
  378. /*  ParseNonSpaceChar                                          */
  379. /*                                                             */
  380. /*  Parse the next non-space character.                        */
  381. /*                                                             */
  382. /***************************************************************/
  383. #ifdef HAVE_PROTOS
  384. PUBLIC int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
  385. #else
  386. int ParseNonSpaceChar(p, err, peek)
  387. ParsePtr p;
  388. int *err;
  389. int peek;
  390. #endif
  391. {
  392.    int ch;
  393.  
  394.    ch = ParseChar(p, err, 1);
  395.    if (*err) return 0;
  396.  
  397.    while (isspace(ch)) {
  398.       ParseChar(p, err, 0);   /* Guaranteed to work */
  399.       ch = ParseChar(p, err, 1);
  400.       if (*err) return 0;
  401.    }
  402.    if (!peek) ch = ParseChar(p, err, 0);  /* Guaranteed to work */
  403.    return ch;
  404. }
  405.  
  406. /***************************************************************/
  407. /*                                                             */
  408. /*  ParseToken                                                 */
  409. /*                                                             */
  410. /*  Parse a token delimited by whitespace.                     */
  411. /*                                                             */
  412. /***************************************************************/
  413. #ifdef HAVE_PROTOS
  414. PUBLIC int ParseToken(ParsePtr p, char *out)
  415. #else
  416. int ParseToken(p, out)
  417. ParsePtr p;
  418. char *out;
  419. #endif
  420. {
  421.    int c, err;
  422.    int len = 0;
  423.    
  424.    *out = 0;
  425.  
  426.    c = ParseChar(p, &err, 0);
  427.    if (err) return err;
  428.    while (c && isspace(c)) {
  429.       c = ParseChar(p, &err, 0);
  430.       if (err) return err;
  431.    }
  432.    if (!c) return OK;
  433.    *out++ = c;
  434.    len++;
  435.  
  436.    while (c && !isspace(c)) {
  437.       c = ParseChar(p, &err, 0);
  438.       if (err) return err;
  439.       if (len < TOKSIZE && c && !isspace(c)) {
  440.          *out++ = c;
  441.      len++;
  442.       }
  443.    }
  444.    *out = 0;
  445.    return OK;
  446. }
  447.  
  448. /***************************************************************/
  449. /*                                                             */
  450. /*  ParseIdentifier                                            */
  451. /*                                                             */
  452. /*  Parse a valid identifier - ie, alpha or underscore         */
  453. /*  followed by alphanum.  Return E_BAD_ID if identifier is    */
  454. /*  invalid.                                                   */
  455. /*                                                             */
  456. /***************************************************************/
  457. #ifdef HAVE_PROTOS
  458. PUBLIC int ParseIdentifier(ParsePtr p, char *out)
  459. #else
  460. int ParseIdentifier(p, out)
  461. ParsePtr p;
  462. char *out;
  463. #endif
  464. {
  465.    int c, err;
  466.    int len = 0;
  467.    
  468.    *out = 0;
  469.  
  470.    c = ParseChar(p, &err, 0);
  471.    if (err) return err;
  472.    while (c && isspace(c)) {
  473.       c = ParseChar(p, &err, 0);
  474.       if (err) return err;
  475.    }
  476.    if (!c) return E_EOLN;
  477.    if (c != '_' && !isalpha(c)) return E_BAD_ID;
  478.    *out++ = c;
  479.    *out = 0;
  480.    len++;
  481.  
  482.    while (1) {
  483.       c = ParseChar(p, &err, 1);
  484.       if (err) return err;
  485.       if (c != '_' && !isalnum(c)) return OK;
  486.  
  487.       if (len < TOKSIZE) {
  488.      c = ParseChar(p, &err, 0);  /* Guaranteed to work */
  489.      *out++ = c;
  490.      *out = 0;
  491.      len++;
  492.       }
  493.    }
  494. }
  495. /***************************************************************/
  496. /*                                                             */
  497. /* EvaluateExpr                                                */
  498. /*                                                             */
  499. /* We are expecting an expression here.  Evaluate it and       */
  500. /* return the value.                                           */
  501. /*                                                             */
  502. /***************************************************************/
  503. #ifdef HAVE_PROTOS
  504. PUBLIC int EvaluateExpr(ParsePtr p, Value *v)
  505. #else
  506. int EvaluateExpr(p, v)
  507. ParsePtr p;
  508. Value *v;
  509. #endif
  510. {
  511.  
  512.    int bracketed = 0;
  513.    int r;
  514.  
  515.    if (p->isnested) return E_PARSE_ERR;  /* Can't nest expressions */
  516.    while (isspace(*p->pos)) (p->pos)++;
  517.    if (!p->pos) return E_PARSE_ERR;      /* Missing expression */
  518.    if (*p->pos == BEG_OF_EXPR) {
  519.       (p->pos)++;
  520.       bracketed = 1;
  521.    }
  522.    r = EvalExpr(&(p->pos), v);
  523.    if (r) return r;
  524.    if (bracketed) {
  525.       if (*p->pos != END_OF_EXPR) return E_MISS_END;
  526.       (p->pos)++;
  527.    }
  528.    return OK;
  529. }
  530.  
  531. /***************************************************************/
  532. /*                                                             */
  533. /*  Eprint - print an error message.                           */
  534. /*                                                             */
  535. /***************************************************************/
  536. #ifdef HAVE_STDARG
  537. #ifdef HAVE_PROTOS
  538. PUBLIC void Eprint(const char *fmt, ...)
  539. #else
  540. void Eprint(fmt)
  541. char *fmt;
  542. #endif
  543. #else
  544. /*VARARGS0*/
  545. void Eprint(va_alist)
  546. va_dcl
  547. #endif
  548. {
  549.    va_list argptr;
  550. #ifndef HAVE_STDARG
  551.    char *fmt;
  552. #endif
  553.    
  554.    /* Check if more than one error msg. from this line */
  555.    if (!FreshLine && !ShowAllErrors) return;
  556.  
  557.    if (FreshLine) {
  558.       FreshLine = 0;
  559.       (void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
  560.       if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
  561.    } else fprintf(ErrFp, "       ");
  562.  
  563. #ifdef HAVE_STDARG
  564.    va_start(argptr, fmt);
  565. #else
  566.    va_start(argptr);
  567.    fmt = va_arg(argptr, char *);
  568. #endif
  569.    (void) vfprintf(ErrFp, fmt, argptr);
  570.    (void) fputc('\n', ErrFp);
  571. #ifndef HAVE_STDARG
  572.    va_end(argptr)
  573. #endif
  574.    return;
  575. }
  576.  
  577. /***************************************************************/
  578. /*                                                             */
  579. /*  OutputLine                                                 */
  580. /*                                                             */
  581. /*  Output a line from memory buffer to a file pointer.  This  */
  582. /*  simply involves escaping newlines.                         */
  583. /*                                                             */
  584. /***************************************************************/
  585. #ifdef HAVE_PROTOS
  586. PUBLIC void OutputLine(FILE *fp)
  587. #else
  588. void OutputLine(fp)
  589. FILE *fp;
  590. #endif
  591. {
  592.    register char *s = CurLine;
  593.    while (*s) {
  594.       if (*s == '\n') putc('\\', fp);
  595.       putc(*s, fp);
  596.       s++;
  597.    }
  598.    if (*(s-1) != '\n') putc('\n', fp);
  599. }
  600.  
  601. /***************************************************************/
  602. /*                                                             */
  603. /*  CreateParser                                               */
  604. /*                                                             */
  605. /*  Create a parser given a string buffer                      */
  606. /*                                                             */
  607. /***************************************************************/
  608. #ifdef HAVE_PROTOS
  609. PUBLIC void CreateParser(char *s, ParsePtr p)
  610. #else
  611. void CreateParser(s, p)
  612. char *s;
  613. ParsePtr p;
  614. #endif
  615. {
  616.    p->text = s;
  617.    p->pos = s;
  618.    p->isnested = 0;
  619.    p->epos = NULL;
  620.    p->etext = NULL;
  621.    p->allownested = 1;
  622.    TokenPushed = NULL;
  623. }
  624.  
  625. /***************************************************************/
  626. /*                                                             */
  627. /*  DestroyParser                                              */
  628. /*                                                             */
  629. /*  Destroy a parser, freeing up resources used.               */
  630. /*                                                             */
  631. /***************************************************************/
  632. #ifdef HAVE_PROTOS
  633. PUBLIC void DestroyParser(ParsePtr p)
  634. #else
  635. void DestroyParser(p)
  636. ParsePtr p;
  637. #endif
  638. {
  639.    if (p->isnested && p->etext) {
  640.       free(p->etext);
  641.       p->etext = NULL;
  642.       p->isnested = 0;
  643.    }
  644. }
  645.  
  646. /***************************************************************/
  647. /*                                                             */
  648. /*  PushToken - one level of token pushback.  This is          */
  649. /*  GLOBAL, not on a per-parser basis.                         */
  650. /*                                                             */
  651. /***************************************************************/
  652. #ifdef HAVE_PROTOS
  653. PUBLIC void PushToken(const char *tok)
  654. #else
  655. void PushToken(tok)
  656. char *tok;
  657. #endif
  658. {
  659.    TokenPushed = TPushBuffer;
  660.    strcpy(TPushBuffer, tok);
  661.    strcat(TPushBuffer, " ");  /* Separate the pushed token from the next
  662.                          token */
  663.    
  664. }
  665.  
  666. /***************************************************************/
  667. /*                                                             */
  668. /*  SystemTime                                                 */
  669. /*                                                             */
  670. /*  Return the system time in seconds past midnight            */
  671. /*                                                             */
  672. /***************************************************************/
  673. #ifdef HAVE_PROTOS
  674. PUBLIC long SystemTime(void)
  675. #else
  676. long SystemTime()
  677. #endif
  678. {
  679. #ifdef __MSDOS__
  680. #ifdef __TURBOC__
  681. /* Get time in Turbo C */
  682.  
  683.    struct time t;
  684.  
  685.    gettime(&t);
  686.    return (long) t.ti_hour * 3600L + (long) t.ti_min * 60L +
  687.       (long) t.ti_sec;
  688.  
  689. #else
  690. /* Get time in Microsoft C */
  691.    struct dostime_t tloc;
  692.    _dos_gettime(&tloc);
  693.    return (long) tloc.hour * 3600L + (long) tloc.minute * 60L +
  694.       (long) tloc.second;
  695.  
  696. #endif
  697. #else
  698. /* Get time in Unix */
  699.   time_t tloc;
  700.   struct tm *t;
  701.  
  702.    (void) time(&tloc);
  703.    t = localtime(&tloc);
  704.    return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
  705.       (long) t->tm_sec;
  706. #endif
  707. }
  708. /***************************************************************/
  709. /*                                                             */
  710. /*  SystemDate                                                 */
  711. /*                                                             */
  712. /*  Obtains today's date.  Returns Julian date or -1 for       */
  713. /*  failure.  (Failure happens if sys date is before BASE      */
  714. /*  year.)                                                     */
  715. /*                                                             */
  716. /***************************************************************/
  717. #ifdef HAVE_PROTOS
  718. PUBLIC int SystemDate(int *y, int *m, int *d)
  719. #else
  720. int SystemDate(y, m, d)
  721. int *d;
  722. int *m;
  723. int *y;
  724. #endif
  725. {
  726. #ifdef __MSDOS__
  727. #ifdef __TURBOC__
  728. /* Get today's date in Turbo C */
  729.    struct date da;
  730.  
  731.    getdate(&da);
  732.    *y = da.da_year;
  733.    *m = da.da_mon - 1;
  734.    *d = da.da_day;
  735. #else
  736. /* Get today's date in Microsoft C */
  737.    struct dosdate_t buf;
  738.  
  739.    _dos_getdate(&buf);
  740.  
  741.    *d = buf.day;
  742.    *m = buf.month - 1;
  743.    *y = buf.year;
  744. #endif
  745. #else
  746. /* Get today's date in UNIX */
  747.   time_t tloc;
  748.   struct tm *t;
  749.  
  750.    (void) time(&tloc);
  751.    t = localtime(&tloc);
  752.  
  753.    *d = t->tm_mday;
  754.    *m = t->tm_mon;
  755.    *y = t->tm_year + 1900;
  756. #endif
  757.    return Julian(*y, *m, *d);
  758. }
  759.  
  760.  
  761. /***************************************************************/
  762. /*                                                             */
  763. /*  DoIf - handle the IF command.                              */
  764. /*                                                             */
  765. /***************************************************************/
  766. #ifdef HAVE_PROTOS
  767. PUBLIC int DoIf(ParsePtr p)
  768. #else
  769. int DoIf(p)
  770. ParsePtr p;
  771. #endif
  772. {
  773.    Value v;
  774.    int r;
  775.    unsigned syndrome;
  776.  
  777.    if (NumIfs >= IF_NEST) return E_NESTED_IF;
  778.  
  779.    if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
  780.    else {
  781.       if (r = EvaluateExpr(p, &v)) {
  782.          syndrome = IF_TRUE | BEFORE_ELSE;
  783.      Eprint("%s", ErrMsg[r]);
  784.       } else 
  785.          if ( (v.type != STR_TYPE && v.v.val) ||
  786.               (v.type == STR_TYPE && strcmp(v.v.str, "")) )
  787.             syndrome = IF_TRUE | BEFORE_ELSE;
  788.          else
  789.             syndrome = IF_FALSE | BEFORE_ELSE;
  790.    }
  791.  
  792.    NumIfs++;
  793.    IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
  794.    IfFlags |= syndrome << (2 * NumIfs - 2);
  795.    if (ShouldIgnoreLine()) return OK;
  796.    return VerifyEoln(p);
  797. }
  798.  
  799.  
  800. /***************************************************************/
  801. /*                                                             */
  802. /*  DoElse - handle the ELSE command.                          */
  803. /*                                                             */
  804. /***************************************************************/
  805. #ifdef HAVE_PROTOS
  806. PUBLIC int DoElse(ParsePtr p)
  807. #else
  808. int DoElse(p)
  809. ParsePtr p;
  810. #endif
  811. {
  812.    unsigned syndrome;
  813.  
  814.    if (!NumIfs) return E_ELSE_NO_IF;
  815.  
  816.    syndrome = IfFlags >> (2 * NumIfs - 2);
  817.  
  818.    if ((syndrome & IF_ELSE_MASK) == AFTER_ELSE) return E_ELSE_NO_IF;
  819.  
  820.    IfFlags |= AFTER_ELSE << (2 * NumIfs - 2);
  821.    return VerifyEoln(p);
  822. }
  823.  
  824. /***************************************************************/
  825. /*                                                             */
  826. /*  DoEndif - handle the Endif command.                        */
  827. /*                                                             */
  828. /***************************************************************/
  829. #ifdef HAVE_PROTOS
  830. PUBLIC int DoEndif(ParsePtr p)
  831. #else
  832. int DoEndif(p)
  833. ParsePtr p;
  834. #endif
  835. {
  836.    if (!NumIfs) return E_ENDIF_NO_IF;
  837.    NumIfs--;
  838.    return VerifyEoln(p);
  839. }
  840.  
  841. /***************************************************************/
  842. /*                                                             */
  843. /*  DoIfTrig                                                   */
  844. /*                                                             */
  845. /*  Handle the IFTRIG command.                                 */
  846. /*                                                             */
  847. /***************************************************************/
  848. #ifdef HAVE_PROTOS
  849. PUBLIC int DoIfTrig(ParsePtr p)
  850. #else
  851. int DoIfTrig(p)
  852. ParsePtr p;
  853. #endif
  854. {
  855.    int r;
  856.    unsigned syndrome;
  857.    Trigger trig;
  858.    TimeTrig tim;
  859.    int jul;
  860.  
  861.  
  862.    if (NumIfs >= IF_NEST) return E_NESTED_IF;
  863.    if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
  864.    else {
  865.       if (r=ParseRem(p, &trig, &tim)) return r;
  866.       if (trig.typ != NO_TYPE) return E_PARSE_ERR;
  867.       jul = ComputeTrigger(JulianToday, &trig, &r);
  868.       if (r) syndrome = IF_TRUE | BEFORE_ELSE;
  869.       else {
  870.          if (ShouldTriggerReminder(&trig, &tim, jul))
  871.         syndrome = IF_TRUE | BEFORE_ELSE;
  872.      else
  873.         syndrome = IF_FALSE | BEFORE_ELSE;
  874.       }
  875.    }
  876.    NumIfs++;
  877.    IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
  878.    IfFlags |= syndrome << (2 * NumIfs - 2);
  879.    return OK;
  880. }
  881.  
  882.        
  883. /***************************************************************/
  884. /*                                                             */
  885. /*  ShouldIgnoreLine - given the current state of the IF       */
  886. /*  stack, should we ignore the current line?                  */
  887. /*                                                             */
  888. /***************************************************************/
  889. #ifdef HAVE_PROTOS
  890. PUBLIC int ShouldIgnoreLine(void)
  891. #else
  892. int ShouldIgnoreLine()
  893. #endif
  894. {
  895.    register int i, syndrome;
  896.  
  897. /* Algorithm - go from outer to inner, and if any should be ignored, then
  898.    ignore the whole. */
  899.  
  900.    for (i=0; i<NumIfs; i++) {
  901.       syndrome = (IfFlags >> (i*2)) & IF_MASK;
  902.       if (syndrome == IF_TRUE+AFTER_ELSE ||
  903.           syndrome == IF_FALSE+BEFORE_ELSE) return 1;
  904.    }
  905.    return 0;
  906. }
  907.  
  908. /***************************************************************/
  909. /*                                                             */
  910. /*  VerifyEoln                                                 */
  911. /*                                                             */
  912. /*  Verify that current line contains no more tokens.          */
  913. /*                                                             */
  914. /***************************************************************/
  915. #ifdef HAVE_PROTOS
  916. PUBLIC int VerifyEoln(ParsePtr p)
  917. #else
  918. int VerifyEoln(p)
  919. ParsePtr p;
  920. #endif
  921. {
  922.    int r;
  923.  
  924.    if (r = ParseToken(p, TokBuffer)) return r;
  925.    if (*TokBuffer && (*TokBuffer != '#') && (*TokBuffer != ';')) {
  926.       Eprint("Expecting end-of-line, found '%s'", TokBuffer);
  927.       return E_EXTRANEOUS_TOKEN;
  928.    }
  929.    return OK;
  930. }
  931.  
  932. /***************************************************************/
  933. /*                                                             */
  934. /*  DoDebug                                                    */
  935. /*                                                             */
  936. /*  Set the debug options under program control.               */
  937. /*                                                             */
  938. /***************************************************************/
  939. #ifdef HAVE_PROTOS
  940. PUBLIC int DoDebug(ParsePtr p)
  941. #else
  942. int DoDebug(p)
  943. ParsePtr p;
  944. #endif
  945. {
  946.    int err;
  947.    int ch;
  948.    int val=1;     
  949.  
  950.    while(1) {
  951.       ch = ParseChar(p, &err, 0);
  952.       if (err) return err;
  953.       switch(ch) {
  954.          case '#':
  955.      case ';':
  956.      case 0:
  957.         return OK;
  958.  
  959.      case ' ':
  960.      case '\t':
  961.         break;
  962.  
  963.      case '+':
  964.         val = 1;
  965.         break;
  966.  
  967.      case '-':
  968.         val = 0;
  969.         break;
  970.  
  971.       case 'e':
  972.       case 'E':
  973.         if (val) DebugFlag |=  DB_ECHO_LINE;
  974.         else     DebugFlag &= ~DB_ECHO_LINE;
  975.         break;
  976.  
  977.       case 'x':
  978.       case 'X':
  979.         if (val) DebugFlag |=  DB_PRTEXPR;
  980.         else     DebugFlag &= ~DB_PRTEXPR;
  981.         break;
  982.  
  983.       case 't':
  984.       case 'T':
  985.         if (val) DebugFlag |=  DB_PRTTRIG;
  986.         else     DebugFlag &= ~DB_PRTTRIG;
  987.         break;
  988.  
  989.       case 'v':
  990.       case 'V':
  991.         if (val) DebugFlag |=  DB_DUMP_VARS;
  992.         else     DebugFlag &= ~DB_DUMP_VARS;
  993.         break;
  994.  
  995.       case 'l':
  996.       case 'L':
  997.         if (val) DebugFlag |=  DB_PRTLINE;
  998.         else     DebugFlag &= ~DB_PRTLINE;
  999.         break;
  1000.  
  1001.       }
  1002.    }
  1003. }
  1004.  
  1005. /***************************************************************/
  1006. /*                                                             */
  1007. /*  DoBanner                                                   */
  1008. /*                                                             */
  1009. /*  Set the banner to be printed just before the first         */
  1010. /*  reminder is issued.                                        */
  1011. /*                                                             */
  1012. /***************************************************************/
  1013. #ifdef HAVE_PROTOS
  1014. PUBLIC int DoBanner(ParsePtr p)
  1015. #else
  1016. int DoBanner(p)
  1017. ParsePtr p;
  1018. #endif
  1019. {
  1020.    int err;
  1021.    int c;
  1022.    char buf[LINELEN];   /* So we don't mess up the banner if an error occurs */
  1023.    char *s;
  1024.  
  1025.    c = ParseChar(p, &err, 0);
  1026.    if (err) return err;
  1027.    while (isspace(c)) {
  1028.       c = ParseChar(p, &err, 0);
  1029.       if (err) return err;
  1030.    }
  1031.    if (!c) return E_EOLN;
  1032.    s = buf;
  1033.  
  1034.    while(c) {
  1035.       *s++ = c;
  1036.       c = ParseChar(p, &err, 0);
  1037.       if (err) return err;
  1038.    }
  1039.    *s++ = 0;
  1040.    strcpy(Banner, buf);
  1041.    return OK;
  1042. }
  1043.  
  1044. /***************************************************************/
  1045. /*                                                             */
  1046. /*  DoRun                                                      */
  1047. /*                                                             */
  1048. /*  Enable or disable the RUN command under program control    */
  1049. /*                                                             */
  1050. /*                                                             */
  1051. /***************************************************************/
  1052. #ifdef HAVE_PROTOS
  1053. PUBLIC int DoRun(ParsePtr p)
  1054. #else
  1055. int DoRun(p)
  1056. ParsePtr p;
  1057. #endif
  1058. {
  1059.    int r;
  1060.  
  1061.    if (!TopLevel())
  1062.       return OK; /* Silently ignore RUN command in included file */
  1063.  
  1064.    if (r=ParseToken(p, TokBuffer)) return r;
  1065.  
  1066.    if (StriEq(TokBuffer, "ON"))
  1067.       RunDisabled &= ~RUN_SCRIPT;
  1068.    else if (StriEq(TokBuffer, "OFF"))
  1069.       RunDisabled |= RUN_SCRIPT;
  1070.    else return E_PARSE_ERR;
  1071.  
  1072.    return VerifyEoln(p);
  1073. }
  1074.  
  1075. /***************************************************************/
  1076. /*                                                             */
  1077. /*  DoErrMsg                                                   */
  1078. /*                                                             */
  1079. /*  Issue an error message under program control.              */
  1080. /*                                                             */
  1081. /***************************************************************/
  1082. #ifdef HAVE_PROTOS
  1083. PUBLIC int DoErrMsg(ParsePtr p)
  1084. #else
  1085. int DoErrMsg(p)
  1086. ParsePtr p;
  1087. #endif
  1088. {
  1089.    TimeTrig tt;
  1090.    Trigger t;
  1091.    int r;
  1092.    char *s;
  1093.  
  1094.    t.typ = MSG_TYPE;
  1095.    tt.ttime = SystemTime() / 60;
  1096.    if (r=DoSubst(p, SubstBuffer, &t, &tt, JulianToday, NORMAL_MODE)) return r;
  1097.    s = SubstBuffer;
  1098.    while (isspace(*s)) s++;
  1099.    fprintf(ErrFp, "%s\n", s);
  1100.    return OK;
  1101. }
  1102.  
  1103.